//
// Created by lihengliu on 2023/4/3.
//
#include "audiovideo.h"
#include <pthread.h>
#include <queue>
#include <cstdint>
#include <android/log.h>

#define LOG_TAG "AudioVideo"
#define ALOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
#define ALOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
#define ALOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
#define ALOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
#define ALOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))


#define MAX_READ_CACHE 60
#define MAX_AUDIO_FRME_SIZE 48000 * 4

extern "C" {
  #include<libavcodec/avcodec.h>
  #include<libavformat/avformat.h>
  #include<libavutil/imgutils.h>
  #include<libswscale/swscale.h>
  #include<libswresample/swresample.h>
  #include<libavutil/time.h>
}

using namespace std;

struct FFmpegInfo{
    AVFormatContext *pFormatCtx;//封装格式上下文
    AVCodecContext *pVideoCodecCtx;//视频解码器上下文
    AVCodecContext *pAudioCodecCtx;//音频解码器上下文
    AVCodec * pVideoCodec;//视频解码器
    AVCodec * pAudioCodec;//音频解码器
    int max_stream;//总共有多少流
    int video_stream_index;//视频流下标
    int audio_stream_count;//音频流个数
    int *audio_stream_indexs;//音频流下标集合
    int subtitle_stream_count;//字幕流个数
    int *subtitle_stream_indexs;//字幕流下标集合
    int64_t video_clock;//当前视频的时间
    int64_t audio_clock;//当前音频的时间
};

struct POSIXInfo{
    pthread_t read_id;//读文件的线程id
    pthread_t playVideo_id;//播放视频的线程id
    pthread_t playAudio_id;//播放音频的线程id
    pthread_mutex_t pthread_mutex;
    pthread_cond_t pthread_cond;
};

FFmpegInfo *ffmpegInfo;
queue<AVPacket*> videoAVPackets;//未解码的视频数据缓存队列
queue<AVPacket*> audioAVPackets;//未解码的音频数据缓存队列
POSIXInfo* posixInfo;
DecodecListener* pDecodecListener;//解码监听接口

bool decodec_flag = false;

/**
 * 注册组件
 */
void initFFmpeg() {}

/**
 * 初始化结构体FFmpegInfo
 * 初始化视频解码器和音频解码器
 * @param path
 */
void initFFmpegInfo(const char *path) {
    ffmpegInfo = (FFmpegInfo *) malloc(sizeof(FFmpegInfo));
    //初始化 AVFormatContext *pFormatCtx
    ffmpegInfo->pFormatCtx = avformat_alloc_context();
    if (avformat_open_input(&ffmpegInfo->pFormatCtx, path, nullptr, nullptr) != 0) {
        ALOGD("打开输入文件失败");
        return;
    }

    if (avformat_find_stream_info(ffmpegInfo->pFormatCtx, nullptr) < 0) {
        ALOGD("获取视频文件信息失败");
        return;
    }
    //输出视频信息
    av_dump_format(ffmpegInfo->pFormatCtx, -1, path, 0);
    ffmpegInfo->max_stream = ffmpegInfo->pFormatCtx->nb_streams > 0 ? ffmpegInfo->pFormatCtx->nb_streams : 0;

    if (ffmpegInfo->max_stream == 0) {
        ALOGD("没有流");
        return;
    }
    ffmpegInfo->audio_stream_count = 0;
    ffmpegInfo->subtitle_stream_count = 0;
    for (int i = 0; i < ffmpegInfo->max_stream; ++i) {
        if (ffmpegInfo->pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
            ffmpegInfo->video_stream_index = i;//获取视频流的索引（下标）位置
        } else if (ffmpegInfo->pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
            ffmpegInfo->audio_stream_count++;//音频流个数+1
        } else if (ffmpegInfo->pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
            ffmpegInfo->subtitle_stream_count++;//字幕流个数+1
        }
    }
    //获得音频流和字幕流下标集合
    AVMediaType temp[] = {AVMEDIA_TYPE_AUDIO, AVMEDIA_TYPE_SUBTITLE};
    for (int j = 0; j < 2; ++j) {
        AVMediaType type = temp[j];
        int index = 0;
        if (type == AVMEDIA_TYPE_AUDIO && ffmpegInfo->audio_stream_count > 0) {//存放音频流下标集合
            ffmpegInfo->audio_stream_indexs = (int *) malloc(sizeof(int) * ffmpegInfo->audio_stream_count);
            for (int i = 0; i < ffmpegInfo->max_stream; ++i) {
                if (ffmpegInfo->pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
                    ffmpegInfo->audio_stream_indexs[index++] = i;
                }
            }
        } else if (type == AVMEDIA_TYPE_SUBTITLE && ffmpegInfo->subtitle_stream_count > 0) {//存放字幕流下标集合
            ffmpegInfo->subtitle_stream_indexs = (int *) malloc(
                    sizeof(int) * ffmpegInfo->subtitle_stream_count);
            for (int i = 0; i < ffmpegInfo->max_stream; ++i) {
                if (ffmpegInfo->pFormatCtx->streams[i]->codec->codec_type ==
                    AVMEDIA_TYPE_SUBTITLE) {
                    ffmpegInfo->subtitle_stream_indexs[index++] = i;
                }
            }
        }
    }

    if (ffmpegInfo -> video_stream_index == -1){
        ALOGD("没有视频流");
    } else{
        ffmpegInfo->pVideoCodecCtx = ffmpegInfo->pFormatCtx->streams[ffmpegInfo->video_stream_index]->codec;
        ffmpegInfo->pVideoCodec = avcodec_find_decoder(ffmpegInfo->pVideoCodecCtx->codec_id);
        //打开编码器
        if(avcodec_open2(ffmpegInfo->pVideoCodecCtx,ffmpegInfo->pVideoCodec,nullptr) < 0){
            ALOGD("打开视频编码器失败");
            return;
        }
    }

    if (ffmpegInfo -> audio_stream_count == 0){
        ALOGD("没有音频流");
    } else{
        ffmpegInfo->pAudioCodecCtx = ffmpegInfo->pFormatCtx->streams[ffmpegInfo->audio_stream_indexs[0]]->codec;//获取第一个音频流的解码器上下文
        ffmpegInfo->pAudioCodec = avcodec_find_decoder(ffmpegInfo->pAudioCodecCtx->codec_id);
        if(avcodec_open2(ffmpegInfo->pAudioCodecCtx,ffmpegInfo->pAudioCodec,nullptr) < 0){
            ALOGD("打开音频编码器失败");
        }
    }

    if (ffmpegInfo -> subtitle_stream_count == 0){
        ALOGD("没有字幕流");
    }
}

void destroyFFmpegInfo(){
    //关闭解编码器
    if (ffmpegInfo->pVideoCodecCtx != nullptr){
        avcodec_close(ffmpegInfo->pVideoCodecCtx);
    }
    if (ffmpegInfo->pAudioCodecCtx != nullptr){
        avcodec_close(ffmpegInfo->pAudioCodecCtx);
    }
    if (&ffmpegInfo->pFormatCtx != nullptr){
        //关闭输入文件
        avformat_close_input(&ffmpegInfo->pFormatCtx);
    }
    if (ffmpegInfo->audio_stream_indexs != nullptr){
        free(ffmpegInfo->audio_stream_indexs);
        ffmpegInfo->audio_stream_indexs = nullptr;
    }
    if (ffmpegInfo->subtitle_stream_indexs != nullptr){
        free(ffmpegInfo->subtitle_stream_indexs);
        ffmpegInfo->subtitle_stream_indexs = nullptr;
    }
    free(ffmpegInfo);
    ffmpegInfo = nullptr;
}

void initPOSIXInfo(){
    posixInfo = (POSIXInfo*)malloc(sizeof(POSIXInfo));
    pthread_mutex_init(&posixInfo->pthread_mutex, nullptr);
    pthread_cond_init(&posixInfo->pthread_cond, nullptr);
}

void destroyPOSIXInfo(){
    pthread_mutex_destroy(&posixInfo->pthread_mutex);
    pthread_cond_destroy(&posixInfo->pthread_cond);
    free(posixInfo);
    posixInfo = nullptr;
}

/**
 * 读数据
 * @param arg
 * @return
 */
void* run_read(void* arg){
    ALOGD("read 线程 running");
    AVPacket *pPacket = av_packet_alloc();
//    av_seek_frame(ffmpegInfo->pFormatCtx,ffmpegInfo->video_stream_index,5000,NULL);
//    av_seek_frame(ffmpegInfo->pFormatCtx,ffmpegInfo->audio_stream_indexs[0],5000,NULL);
    while (av_read_frame(ffmpegInfo->pFormatCtx, pPacket) == 0) {
        ALOGD("读ing");
        //读取
        pthread_mutex_lock(&posixInfo->pthread_mutex);
        AVPacket *temp;
        if (pPacket->stream_index == ffmpegInfo->video_stream_index) {
            temp = av_packet_alloc();

            //av_copy_packet(temp, pPacket);
            av_packet_ref(temp, pPacket);

            videoAVPackets.push(temp);
            ALOGD("视频缓冲区大小：%lu", videoAVPackets.size());
        } else if (pPacket->stream_index == ffmpegInfo->audio_stream_indexs[0]) {
            temp = av_packet_alloc();

            //av_copy_packet(temp, pPacket);
            av_packet_ref(temp, pPacket);

            audioAVPackets.push(temp);
            ALOGD("音频缓冲区大小：%lu", videoAVPackets.size());
        }

        while (videoAVPackets.size() >= MAX_READ_CACHE || audioAVPackets.size() >= MAX_READ_CACHE) {
            pthread_cond_wait(&posixInfo->pthread_cond, &posixInfo->pthread_mutex);
        }
        pthread_cond_broadcast(&posixInfo->pthread_cond);
        pthread_mutex_unlock(&posixInfo->pthread_mutex);

    }

    av_free(pPacket);
    return nullptr;
}

/**
 * 启动读数据的线程
 */
void read() {
    pthread_create(&posixInfo->read_id, nullptr, run_read, nullptr);
}

/**
 * 获取视频数据并解码
 * @return
 */
void *run_video_decodec(void *) {
    int got_picture_ptr;//如果没有帧可以解压缩，则为零，否则为非零。
    int countFrame = 0;
    int64_t start_PTS = 0;
    //初始化 AVFrame *pFrame -> 存放解码后的数据
    AVFrame *pFrame = av_frame_alloc();
    //AVFrame *pFrameRGBA -> 存放转换为RGBA后的数据
    AVFrame *pFrameRGBA = av_frame_alloc();
    int w = ffmpegInfo->pVideoCodecCtx->width;
    int h = ffmpegInfo->pVideoCodecCtx->height;
    auto oneFrameSize = (size_t) av_image_get_buffer_size(AV_PIX_FMT_RGBA, w, h, 1);
    auto *buff = (uint8_t *) malloc(oneFrameSize);

    //初始化用于格式转换的SwsContext，由于解码出来的帧格式不是RGBA的,在渲染之前需要进行格式转换
    SwsContext *sws_ctx = sws_getContext(w, h, ffmpegInfo->pVideoCodecCtx->pix_fmt,
                                         w, h, AV_PIX_FMT_RGBA,
                                         SWS_BILINEAR,
                                         nullptr,
                                         nullptr,
                                         nullptr);
    if (pDecodecListener != nullptr && pDecodecListener->startDecodecVideo != nullptr) {
        pDecodecListener->startDecodecVideo(nullptr);
    }
//    int64_t startTime = av_gettime();//开始播放的时间
    double time_base_d = av_q2d(ffmpegInfo->pFormatCtx->streams[ffmpegInfo->video_stream_index]->time_base);
//    int frameInterval = (int)(1/(time_base_d * av_q2d(ffmpegInfo->pFormatCtx->streams[ffmpegInfo->video_stream_index]->avg_frame_rate)));
//    int frameRate = (int)(av_q2d(ffmpegInfo->pFormatCtx->streams[ffmpegInfo->video_stream_index]->avg_frame_rate));//帧率
    while (decodec_flag) {
        ALOGD("视频解码ing,%lu", videoAVPackets.size());
        pthread_mutex_lock(&posixInfo->pthread_mutex);
        while (videoAVPackets.empty()) {
            pthread_cond_wait(&posixInfo->pthread_cond, &posixInfo->pthread_mutex);
        }

        AVPacket *pPacket = videoAVPackets.front();
        videoAVPackets.pop();

        pthread_cond_broadcast(&posixInfo->pthread_cond);
        pthread_mutex_unlock(&posixInfo->pthread_mutex);

        ALOGD("222--ffmpegInfo->pVideoCodecCtx");
        //if (avcodec_decode_video2(ffmpegInfo->pVideoCodecCtx, pFrame, &got_picture_ptr, pPacket) < 0) {
        //    ALOGD("解码错误");
        //}

        int packet_value = avcodec_send_packet(ffmpegInfo->pVideoCodecCtx, pPacket);
        if (packet_value != 0) {
            ALOGD("222--packet_value != 0");
            return nullptr;
        }

        //int frame_value = avcodec_receive_frame(ffmpegInfo->pAudioCodecCtx, pFrame);
        //bool condition = packet_value > 0 && frame_value > 0/* && got_frame > 0*/;
        //if (condition)
        while (avcodec_receive_frame(ffmpegInfo->pVideoCodecCtx, pFrame) >= 0)

        //if (got_picture_ptr >= 0)

        {
            ALOGD("222--avcodec_receive_frame(ffmpegInfo->pAudioCodecCtx, pFrame) >= 0");
            if (pPacket->pts != AV_NOPTS_VALUE) {
                pFrame->pts = pPacket->pts;
            }
            /*else {
                pFrame->pts = av_frame_get_best_effort_timestamp(pFrame);
            }*/
            //int64_t thisFramePTS = start_PTS + frameInterval * countFrame;//计算当前帧的PTS
            auto thisFramePTS = (double) pFrame->pts;
            //PTS * time_base = 当前显示的时间（单位s)
            auto time = (int64_t) (thisFramePTS * time_base_d);
            //PTS * time_base = 当前显示的时间（单位s),*1000000转换为微秒
            ffmpegInfo->video_clock = (int64_t) ((thisFramePTS * time_base_d) *1000000);
            countFrame++;
            av_image_fill_arrays(pFrameRGBA->data,
                                 pFrameRGBA->linesize,
                                 (uint8_t *) buff,
                                 AV_PIX_FMT_RGBA,
                                 w, h, 1);
            //格式转换
            sws_scale(sws_ctx, (const uint8_t *const *) pFrame->data,
                      pFrame->linesize, 0, h,
                      pFrameRGBA->data, pFrameRGBA->linesize);
            if (pDecodecListener != nullptr && pDecodecListener->onDecodecVideo != nullptr) {
                //调用回调接口进行绘制
                pDecodecListener->onDecodecVideo(buff, oneFrameSize, w, h, time);
            }

            //视频同步到音频
            //视频比音频快
            if (ffmpegInfo->video_clock > ffmpegInfo->audio_clock) {
                av_usleep((uint) (ffmpegInfo->video_clock - ffmpegInfo->audio_clock));//延迟
            } else {
                //音频比视频快
                //不做延迟
            }
//            //计算标准视频时间（音频同步到视频需要）
//            int64_t showTime = (int64_t)(startTime + ffmpegInfo->video_clock);
//            int64_t thisTime = av_gettime();//当前时间
//            if (thisTime < showTime){ //显示快了，需要放慢速度
            ALOGD("显示快了");
//                av_usleep((uint)(showTime - thisTime));
//            } else if(thisTime > showTime){//显示慢了
//
//            } else{//刚好显示时间正确，一般不会走到这里
//
//            }
        }
        av_packet_unref(pPacket);
        av_free(pPacket);
    }
    free(buff);
    av_free(pFrame);
    av_free(pFrameRGBA);
    sws_freeContext(sws_ctx);

    if (pDecodecListener != nullptr && pDecodecListener->endDecodecVideo != nullptr) {
        pDecodecListener->endDecodecVideo(nullptr);
    }

    return nullptr;
}



/**  11111
 * 获取音频数据并解码
 * @param arg
 * @return
 */
void* run_audio_decodec(void* arg) {
    //初始化 AVFrame *pFrame -> 存放解码后的数据
    AVFrame *pFrame = av_frame_alloc();
    //初始化用于重采样的SwrContext
    //分配重采样SwrContext
    SwrContext *swrCtx = swr_alloc();
    //输入的采样格式
    enum AVSampleFormat in_sample_fmt = ffmpegInfo->pAudioCodecCtx->sample_fmt;
    //输出采样格式16bit PCM
    enum AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16;
    //输入采样率
    int in_sample_rate = ffmpegInfo->pAudioCodecCtx->sample_rate;
    //输出采样率
    int out_sample_rate = 44100;
    //获取输入的声道布局
    long in_ch_layout = reinterpret_cast<int64_t>(ffmpegInfo->pAudioCodecCtx->channel_layout);
    //输出的声道布局（立体声）
    int64_t out_ch_layout = AV_CH_LAYOUT_STEREO;
    //设置参数到SwrContext
    swr_alloc_set_opts(swrCtx,
                       out_ch_layout,
                       out_sample_fmt,
                       out_sample_rate,
                       in_ch_layout,
                       in_sample_fmt,
                       in_sample_rate,
                       0,
                       nullptr);
    //初始化SwrContext
    swr_init(swrCtx);
    //输出的声道个数
    int out_channel_nb = av_get_channel_layout_nb_channels(out_ch_layout);
    //分配存放 16bit 44100 PCM 数据 的内存
    auto *out_buffer = (uint8_t *) av_malloc(MAX_AUDIO_FRME_SIZE);

    if (pDecodecListener != nullptr &&  pDecodecListener->startDecodecAudio != nullptr){
        pDecodecListener->startDecodecAudio(out_sample_rate,out_channel_nb);
    }

    //开始播放的时间
    int64_t startTime = av_gettime();
    double time_base_d = av_q2d(ffmpegInfo->pFormatCtx->streams[ffmpegInfo->audio_stream_indexs[0]]->time_base);

    //int got_frame = 0;
    while (decodec_flag) {
        ALOGD("音频解码ing，%lu", audioAVPackets.size());
        pthread_mutex_lock(&posixInfo->pthread_mutex);

        while (audioAVPackets.empty()/*&& audioAVPackets.size() <= 0*/) {
            pthread_cond_wait(&posixInfo->pthread_cond, &posixInfo->pthread_mutex);
        }

        AVPacket *pPacket = audioAVPackets.front();
        audioAVPackets.pop();

        pthread_cond_broadcast(&posixInfo->pthread_cond);
        pthread_mutex_unlock(&posixInfo->pthread_mutex);

        //七.解码一帧数据
        //int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
        //int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);

        //avcodec_decode_audio4(ffmpegInfo->pAudioCodecCtx, pFrame, &got_frame, pPacket);

        int packet_value = avcodec_send_packet(ffmpegInfo->pAudioCodecCtx, pPacket);
        if (packet_value != 0) {
            return nullptr;
        }

        //int frame_value = avcodec_receive_frame(ffmpegInfo->pAudioCodecCtx, pFrame);
        //bool condition = packet_value > 0 && frame_value > 0/* && got_frame > 0*/;
        //if (condition)
        while (avcodec_receive_frame(ffmpegInfo->pAudioCodecCtx, pFrame) == 0)
        {
            if (pPacket->pts != AV_NOPTS_VALUE) {
                pFrame->pts = pPacket->pts;
            } else {
                AVRational tb = (AVRational) {1, pFrame->sample_rate};
                if (pFrame->pts != AV_NOPTS_VALUE) {
                    pFrame->pts = av_rescale_q(pFrame->pts, ffmpegInfo->pAudioCodecCtx->time_base, tb);
                } else if (pFrame->pts != AV_NOPTS_VALUE) {
                    pFrame->pts = av_rescale_q(pFrame->pts,/*av_codec_get_pkt_timebase(ffmpegInfo->pAudioCodecCtx)*/tb, tb);
                } else {
                    pFrame->pts = pPacket->dts;
                }
            }

            auto thisFramePTS = (double) pFrame->pts;
            //PTS * time_base = 当前显示的时间（单位s）* 1000000 转化为 微秒
            //ffmpegInfo->audio_clock = (int64_t) (thisFramePTS * 1000000 * time_base_d);
            ffmpegInfo->audio_clock = (int64_t) (thisFramePTS * time_base_d * 1000000);

            //AudioTrack是有阻塞的所以可以不需要延迟，因为它按正常速度执行就是标准的音频时间
            bool sleepFlag = false;
            if (sleepFlag) {
                //计算音频标准时间（视频同步到音频需要）
                int64_t showTime = (int64_t) (startTime + ffmpegInfo->audio_clock);
                int64_t thisTime = av_gettime();//当前时间
                if (thisTime < showTime) { //显示快了，需要放慢速度
                    av_usleep((uint) (showTime - thisTime));
                } else if (thisTime > showTime) {
                    //显示慢了，需要加快速度
                } else {
                    //刚好显示时间正确，一般不会走到这里
                }
            }

            //重采样
            swr_convert(swrCtx,
                        &out_buffer,
                        MAX_AUDIO_FRME_SIZE,
                        (const uint8_t **) pFrame->data,
                        pFrame->nb_samples);
            //获取samples（样本，类似于视频的一帧）的大小
            int out_buffer_size = av_samples_get_buffer_size(nullptr,
                                                             out_channel_nb,
                                                             pFrame->nb_samples,
                                                             out_sample_fmt, 1);

            if (pDecodecListener != nullptr && pDecodecListener->onDecodecAudio != nullptr) {
                //调用回调接口进行播放音频
                pDecodecListener->onDecodecAudio(out_buffer, out_buffer_size);
            }
        }

        av_packet_unref(pPacket);
        av_free(pPacket);
    }

    av_free(pFrame);
    av_free(out_buffer);
    swr_free(&swrCtx);

    if (pDecodecListener != nullptr &&  pDecodecListener->endDecodecAudio != nullptr){
        pDecodecListener->endDecodecAudio(nullptr);
    }

    ALOGD("音频解码结束");
    return nullptr;
}

/*void* run_audio_decodec(void* arg) {
    //初始化 AVFrame *pFrame -> 存放解码后的数据
    AVFrame *pFrame = av_frame_alloc();
    //初始化用于重采样的SwrContext
    //分配重采样SwrContext
    SwrContext *swrCtx = swr_alloc();
    //输入的采样格式
    enum AVSampleFormat in_sample_fmt = ffmpegInfo->pAudioCodecCtx->sample_fmt;
    //输出采样格式16bit PCM
    enum AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16;
    //输入采样率
    int in_sample_rate = ffmpegInfo->pAudioCodecCtx->sample_rate;
    //输出采样率
    int out_sample_rate = 44100;
    //获取输入的声道布局
    uint64_t in_ch_layout = ffmpegInfo->pAudioCodecCtx->channel_layout;
    //输出的声道布局（立体声）
    uint64_t out_ch_layout = AV_CH_LAYOUT_STEREO;
    //设置参数到SwrContext
    swr_alloc_set_opts(swrCtx,
                       out_ch_layout, out_sample_fmt, out_sample_rate,
                       in_ch_layout, in_sample_fmt, in_sample_rate,
                       0, nullptr);
    //初始化SwrContext
    swr_init(swrCtx);
    //输出的声道个数
    int out_channel_nb = av_get_channel_layout_nb_channels(out_ch_layout);
    //分配存放 16bit 44100 PCM 数据 的内存
    uint8_t *out_buffer = (uint8_t *) av_malloc(MAX_AUDIO_FRME_SIZE);

    if (pDecodecListener != nullptr &&  pDecodecListener->startDecodecAudio != nullptr){
        pDecodecListener->startDecodecAudio(out_sample_rate,out_channel_nb);
    }

    int64_t startTime = av_gettime();//开始播放的时间
    double time_base_d = av_q2d(ffmpegInfo->pFormatCtx->streams[ffmpegInfo->audio_stream_indexs[0]]->time_base);

    int got_frame = 0;
    while (decodec_flag) {
        ALOGD("音频解码ing，%d", audioAVPackets.size());
        pthread_mutex_lock(&posixInfo->pthread_mutex);

        while (audioAVPackets.size() <= 0) {
            pthread_cond_wait(&posixInfo->pthread_cond, &posixInfo->pthread_mutex);
        }

        AVPacket *pPacket = audioAVPackets.front();
        audioAVPackets.pop();

        pthread_cond_broadcast(&posixInfo->pthread_cond);
        pthread_mutex_unlock(&posixInfo->pthread_mutex);

        //int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
        //int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);

        //七.解码一帧数据
        //avcodec_decode_audio4(ffmpegInfo->pAudioCodecCtx, pFrame, &got_frame, pPacket);
        bool condition = avcodec_send_packet(ffmpegInfo->pVideoCodecCtx,pPacket) > 0
                         && avcodec_receive_frame(ffmpegInfo->pVideoCodecCtx,pFrame) > 0;
        if (condition) {
            if (pPacket->pts != AV_NOPTS_VALUE) {
                pFrame->pts = pPacket->pts;
            } else {
                AVRational tb = (AVRational) {1, pFrame->sample_rate};
                if (pFrame->pts != AV_NOPTS_VALUE) {
                    pFrame->pts = av_rescale_q(pFrame->pts, ffmpegInfo->pAudioCodecCtx->time_base,tb);
                } else if (pFrame->pts != AV_NOPTS_VALUE) {
                    AVRational avRational;
                    pFrame->pts = av_rescale_q(pFrame->pts, avRational*//*av_codec_get_pkt_timebase(ffmpegInfo->pAudioCodecCtx)*//*, tb);
                } else {
                    pFrame->pts = pPacket->dts;
                }
            }

            int64_t thisFrmaePTS = pFrame->pts;
            ffmpegInfo->audio_clock = (int64_t) (thisFrmaePTS * time_base_d *
                                                 1000000);//PTS * time_base = 当前显示的时间（单位s）  *1000000 转化为 微秒

            //AudioTrack是有阻塞的所以可以不需要延迟，因为它按正常速度执行就是标准的音频时间
            bool sleepflag = false;
            if (sleepflag) {
                //计算音频标准时间（视频同步到音频需要）
                int64_t showTime = (int64_t) (startTime + ffmpegInfo->audio_clock);
                int64_t thisTime = av_gettime();//当前时间
                if (thisTime < showTime) { //显示快了，需要放慢速度
                    av_usleep((uint) (showTime - thisTime));
                } else if (thisTime > showTime) {//显示慢了，需要加快速度

                } else {//刚好显示时间正确，一般不会走到这里

                }
            }

            //重采样
            swr_convert(swrCtx,
                        &out_buffer,
                        MAX_AUDIO_FRME_SIZE,
                        (const uint8_t **) pFrame->data,
                        pFrame->nb_samples);
            //获取samples（样本，类似于视频的一帧）的大小
            int out_buffer_size = av_samples_get_buffer_size(nullptr,
                                                             out_channel_nb,
                                                             pFrame->nb_samples,
                                                             out_sample_fmt, 1);

            //ALOGD("音频PTS：%lld，音频DTS：%lld，duration：%lld，pos：%lld",pPacket->pts, pPacket->dts,pPacket->duration, pPacket->pos);
            if (pDecodecListener != nullptr && pDecodecListener->onDecodecAudio != nullptr) {
                pDecodecListener->onDecodecAudio(out_buffer, out_buffer_size);//调用回调接口进行播放音频
            }
        }


        av_packet_unref(pPacket);
        av_free(pPacket);
    }

    av_free(pFrame);
    av_free(out_buffer);
    swr_free(&swrCtx);

    if (pDecodecListener != nullptr &&  pDecodecListener->endDecodecAudio != nullptr){
        pDecodecListener->endDecodecAudio(nullptr);
    }
    ALOGD("音频解码结束");
    return nullptr;
}*/


void startDecodec() {
    ALOGD("startDecodec 开始解码");
    decodec_flag = true;
    pthread_create(&posixInfo->playVideo_id, nullptr, run_video_decodec, nullptr);
    pthread_create(&posixInfo->playAudio_id, nullptr, run_audio_decodec, nullptr);

    pthread_join(posixInfo->read_id, nullptr);
    pthread_join(posixInfo->playVideo_id, nullptr);
    pthread_join(posixInfo->playAudio_id, nullptr);
}

void stopDecodec(bool stop) {
    decodec_flag = false;
}

void setDecodecListener(DecodecListener *decodecListener) {
    pDecodecListener = decodecListener;
}

///**
// * 初始化结构体FFmpegInfo
// * 初始化视频解码器和音频解码器
// * @param path
// */
//void initFFmpegInfo(const char *path) {
//    ffmpegInfo = (FFmpegInfo *) malloc(sizeof(FFmpegInfo));
//    //初始化 AVFormatContext *pFormatCtx
//    ffmpegInfo->pFormatCtx = avformat_alloc_context();
//    if (avformat_open_input(&ffmpegInfo->pFormatCtx, path, nullptr, nullptr) != 0) {
//        ALOGD("打开输入文件失败");
//        return;
//    }
//
//    if (avformat_find_stream_info(ffmpegInfo->pFormatCtx, nullptr) < 0) {
//        ALOGD("获取视频文件信息失败");
//        return;
//    }
//    //输出视频信息
//    av_dump_format(ffmpegInfo->pFormatCtx, -1, path, 0);
//    ffmpegInfo->max_stream = ffmpegInfo->pFormatCtx->nb_streams > 0 ? ffmpegInfo->pFormatCtx->nb_streams : 0;
//
//    if (ffmpegInfo->max_stream == 0) {
//        ALOGD("没有流");
//        return;
//    }
//    ffmpegInfo->audio_stream_count = 0;
//    ffmpegInfo->subtitle_stream_count = 0;
//    for (int i = 0; i < ffmpegInfo->max_stream; ++i) {
//        if (ffmpegInfo->pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
//            ffmpegInfo->video_stream_index = i;//获取视频流的索引（下标）位置
//        } else if (ffmpegInfo->pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
//            ffmpegInfo->audio_stream_count++;//音频流个数+1
//        } else if (ffmpegInfo->pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
//            ffmpegInfo->subtitle_stream_count++;//字幕流个数+1
//        }
//    }
//    //获得音频流和字幕流下标集合
//    AVMediaType temp[] = {AVMEDIA_TYPE_AUDIO, AVMEDIA_TYPE_SUBTITLE};
//    for (int j = 0; j < 2; ++j) {
//        AVMediaType type = temp[j];
//        int index = 0;
//        if (type == AVMEDIA_TYPE_AUDIO && ffmpegInfo->audio_stream_count > 0) {//存放音频流下标集合
//            ffmpegInfo->audio_stream_indexs = (int *) malloc(sizeof(int) * ffmpegInfo->audio_stream_count);
//            for (int i = 0; i < ffmpegInfo->max_stream; ++i) {
//                if (ffmpegInfo->pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
//                    ffmpegInfo->audio_stream_indexs[index++] = i;
//                }
//            }
//        } else if (type == AVMEDIA_TYPE_SUBTITLE && ffmpegInfo->subtitle_stream_count > 0) {//存放字幕流下标集合
//            ffmpegInfo->subtitle_stream_indexs = (int *) malloc(
//                    sizeof(int) * ffmpegInfo->subtitle_stream_count);
//            for (int i = 0; i < ffmpegInfo->max_stream; ++i) {
//                if (ffmpegInfo->pFormatCtx->streams[i]->codecpar->codec_type ==
//                    AVMEDIA_TYPE_SUBTITLE) {
//                    ffmpegInfo->subtitle_stream_indexs[index++] = i;
//                }
//            }
//        }
//    }
//
//    if (ffmpegInfo -> video_stream_index == -1){
//        ALOGD("没有视频流");
//    } else{
//        const AVCodec* avCodec = avcodec_find_decoder(ffmpegInfo->pFormatCtx->streams[ffmpegInfo->video_stream_index]->codecpar->codec_id);
//        AVCodecContext* avCodecContext = avcodec_alloc_context3(avCodec);
//        avCodecContext->thread_count = 1;
//        ffmpegInfo->pVideoCodecCtx = avCodecContext;
//        ffmpegInfo->pVideoCodec = avcodec_find_decoder(ffmpegInfo->pVideoCodecCtx->codec_id);
//        //打开编码器
//        if(avcodec_open2(ffmpegInfo->pVideoCodecCtx,ffmpegInfo->pVideoCodec,nullptr) < 0){
//            ALOGD("打开视频编码器失败");
//            return;
//        }
//    }
//
//    if (ffmpegInfo -> audio_stream_count == 0){
//        ALOGD("没有音频流");
//    } else{
//        const AVCodec* avCodec = avcodec_find_decoder(ffmpegInfo->pFormatCtx->streams[ffmpegInfo->video_stream_index]->codecpar->codec_id);
//        AVCodecContext* avCodecContext = avcodec_alloc_context3(avCodec);
//        avCodecContext->thread_count = 1;
//        ffmpegInfo->pAudioCodecCtx = avCodecContext;//获取第一个音频流的解码器上下文
//        ffmpegInfo->pAudioCodec = avcodec_find_decoder(ffmpegInfo->pAudioCodecCtx->codec_id);
//        if(avcodec_open2(ffmpegInfo->pAudioCodecCtx,ffmpegInfo->pAudioCodec,nullptr) < 0){
//            ALOGD("打开音频编码器失败");
//        }
//    }
//
//    if (ffmpegInfo -> subtitle_stream_count == 0){
//        ALOGD("没有字幕流");
//    }
//}
//
//
//void destroyFFmpegInfo(){
//    //关闭解编码器
//    if (ffmpegInfo->pVideoCodecCtx != nullptr){
//        avcodec_close(ffmpegInfo->pVideoCodecCtx);
//    }
//    if (ffmpegInfo->pAudioCodecCtx != nullptr){
//        avcodec_close(ffmpegInfo->pAudioCodecCtx);
//    }
//    if (&ffmpegInfo->pFormatCtx != nullptr){
//        //关闭输入文件
//        avformat_close_input(&ffmpegInfo->pFormatCtx);
//    }
//    if (ffmpegInfo->audio_stream_indexs != nullptr){
//        free(ffmpegInfo->audio_stream_indexs);
//        ffmpegInfo->audio_stream_indexs = nullptr;
//    }
//    if (ffmpegInfo->subtitle_stream_indexs != nullptr){
//        free(ffmpegInfo->subtitle_stream_indexs);
//        ffmpegInfo->subtitle_stream_indexs = nullptr;
//    }
//    free(ffmpegInfo);
//    ffmpegInfo = nullptr;
//}
//
//
//void initPOSIXInfo(){
//    posixInfo = (POSIXInfo*)malloc(sizeof(POSIXInfo));
//    pthread_mutex_init(&posixInfo->pthread_mutex, nullptr);
//    pthread_cond_init(&posixInfo->pthread_cond, nullptr);
//}
//
//void destroyPOSIXInfo(){
//    pthread_mutex_destroy(&posixInfo->pthread_mutex);
//    pthread_cond_destroy(&posixInfo->pthread_cond);
//    free(posixInfo);
//    posixInfo = nullptr;
//}
//
///**
// * 读数据
// * @param arg
// * @return
// */
//void* run_read(void* arg){
//    ALOGD("read 线程 running");
//    AVPacket *pPacket = av_packet_alloc();
////    av_seek_frame(ffmpegInfo->pFormatCtx,ffmpegInfo->video_stream_index,5000,NULL);
////    av_seek_frame(ffmpegInfo->pFormatCtx,ffmpegInfo->audio_stream_indexs[0],5000,NULL);
//    while (av_read_frame(ffmpegInfo->pFormatCtx,pPacket) == 0){
//        ALOGD("读ing");
//        //读取
//        pthread_mutex_lock(&posixInfo->pthread_mutex);
//        AVPacket *temp;
//        if (pPacket->stream_index == ffmpegInfo->video_stream_index){
//            temp = av_packet_alloc();
//            av_packet_ref(temp,pPacket);
//            videoAVPackets.push(temp);
//            ALOGD("视频缓冲区大小：%d",videoAVPackets.size());
//        } else
//        if(pPacket->stream_index == ffmpegInfo->audio_stream_indexs[0]){
//            temp = av_packet_alloc();
//            av_packet_ref(temp,pPacket);
//            audioAVPackets.push(temp);
//            ALOGD("音频缓冲区大小：%d",videoAVPackets.size());
//        }
//        while(videoAVPackets.size() >= MAX_READ_CACHE  || audioAVPackets.size() >= MAX_READ_CACHE){
//            pthread_cond_wait(&posixInfo->pthread_cond,&posixInfo->pthread_mutex);
//        }
//        pthread_cond_broadcast(&posixInfo->pthread_cond);
//        pthread_mutex_unlock(&posixInfo->pthread_mutex);
//
//    }
//    av_free(pPacket);
//    return nullptr;
//}
//
///**
// * 启动读数据的线程
// */
//void read() {
//    pthread_create(&posixInfo->read_id, nullptr, run_read, nullptr);
//}
//
///**
// * 获取视频数据并解码
// * @return
// */
//void* run_video_decodec(void *){
//    int got_picture_ptr;//如果没有帧可以解压缩，则为零，否则为非零。
//    int countFrame = 0;
//    int64_t start_PTS = 0;
//    //初始化 AVFrame *pFrame -> 存放解码后的数据
//    AVFrame *pFrame = av_frame_alloc();
//    //AVFrame *pFrameRGBA -> 存放转换为RGBA后的数据
//    AVFrame *pFrameRGBA = av_frame_alloc();
//    int w = ffmpegInfo->pVideoCodecCtx->width;
//    int h = ffmpegInfo->pVideoCodecCtx->height;
//    auto oneFrameSize = (size_t)av_image_get_buffer_size(AV_PIX_FMT_RGBA,w,h,1);
//    auto * buff = (uint8_t*)malloc(oneFrameSize);
//
//    //初始化用于格式转换的SwsContext，由于解码出来的帧格式不是RGBA的,在渲染之前需要进行格式转换
//    SwsContext *sws_ctx = sws_getContext(w, h, ffmpegInfo->pVideoCodecCtx->pix_fmt,
//                                         w, h, AV_PIX_FMT_RGBA,
//                                         SWS_BILINEAR, nullptr,
//                                         nullptr, nullptr);
//    if (pDecodecListener != nullptr &&  pDecodecListener->startDecodecVideo != nullptr){
//        pDecodecListener->startDecodecVideo(nullptr);
//    }
////    int64_t startTime = av_gettime();//开始播放的时间
//    double time_base_d = av_q2d(ffmpegInfo->pFormatCtx->streams[ffmpegInfo->video_stream_index]->time_base);
////    int frameInterval = (int)(1/(time_base_d * av_q2d(ffmpegInfo->pFormatCtx->streams[ffmpegInfo->video_stream_index]->avg_frame_rate)));
////    int frameRate = (int)(av_q2d(ffmpegInfo->pFormatCtx->streams[ffmpegInfo->video_stream_index]->avg_frame_rate));//帧率
//    while (decodec_flag){
//        ALOGD("视频解码ing,%d",videoAVPackets.size());
//        pthread_mutex_lock(&posixInfo->pthread_mutex);
//        while (videoAVPackets.size() <= 0){
//            pthread_cond_wait(&posixInfo->pthread_cond,&posixInfo->pthread_mutex);
//        }
//
//        AVPacket *pPacket = videoAVPackets.front();
//        videoAVPackets.pop();
//
//        pthread_cond_broadcast(&posixInfo->pthread_cond);
//        pthread_mutex_unlock(&posixInfo->pthread_mutex);
//
//        //int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
//        //int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
//
//        //if (avcodec_decode_video2(ffmpegInfo->pVideoCodecCtx,pFrame,&got_picture_ptr,pPacket) < 0){
//        //    ALOGD("解码错误");
//        //}
//
//        bool condition = avcodec_send_packet(ffmpegInfo->pVideoCodecCtx,pPacket) >= 0
//                         && avcodec_receive_frame(ffmpegInfo->pVideoCodecCtx,pFrame) >= 0;
//        if (condition){
//
//            if(pPacket->pts != AV_NOPTS_VALUE){
//                pFrame->pts = pPacket->pts;
//            }
//
//            //else{
//            //    pFrame->pts = av_frame_get_best_effort_timestamp(pFrame);
//            //}
////            int64_t thisFrmaePTS = start_PTS + frameInterval * countFrame;//计算当前帧的PTS
//
//            int64_t thisFrmaePTS = pFrame->pts;
//            auto time = (int64_t)(thisFrmaePTS * time_base_d);//PTS * time_base = 当前显示的时间（单位s)
//            ffmpegInfo->video_clock =(int64_t) ((thisFrmaePTS * time_base_d)* 1000000) ; //PTS * time_base = 当前显示的时间（单位s),*1000000转换为微秒
//            //ALOGD("视频PTS：%lld，视频DTS：%lld，duration：%lld，pos：%lld",pFrame->pts,pPacket->dts,pPacket->duration,pPacket->pos);
//            countFrame++;
//            av_image_fill_arrays(pFrameRGBA->data, pFrameRGBA->linesize, (uint8_t*)buff, AV_PIX_FMT_RGBA,w, h, 1);
//            //格式转换
//            sws_scale(sws_ctx,(const uint8_t *const*)pFrame->data,
//                      pFrame->linesize,0,h,
//                      pFrameRGBA->data,pFrameRGBA->linesize);
//            if (pDecodecListener != nullptr &&  pDecodecListener->onDecodecVideo != nullptr){
//                pDecodecListener->onDecodecVideo(buff,oneFrameSize,w,h,time);//调用回调接口进行绘制
//            }
//
//            //视频同步到音频
//
//            //视频比音频快
//            if (ffmpegInfo->video_clock > ffmpegInfo->audio_clock){
//                av_usleep((uint)(ffmpegInfo->video_clock - ffmpegInfo->audio_clock));//延迟
//            } else{
//                //音频比视频快
//                //不做延迟
//            }
//
////            //计算标准视频时间（音频同步到视频需要）
////            int64_t showTime = (int64_t)(startTime + ffmpegInfo->video_clock);
////            int64_t thisTime = av_gettime();//当前时间
////            if (thisTime < showTime){ //显示快了，需要放慢速度
//            ALOGD("显示快了");
////                av_usleep((uint)(showTime - thisTime));
////            } else if(thisTime > showTime){//显示慢了
////
////            } else{//刚好显示时间正确，一般不会走到这里
////
////            }
//
//
//        }
//
//        av_packet_unref(pPacket);
//        av_free(pPacket);
//    }
//    free(buff);
//    av_free(pFrame);
//    av_free(pFrameRGBA);
//    sws_freeContext(sws_ctx);
//
//    if (pDecodecListener != nullptr &&  pDecodecListener->endDecodecVideo != nullptr){
//        pDecodecListener->endDecodecVideo(nullptr);
//    }
//
//    return nullptr;
//}

//void startDecodec() {
//    ALOGD("startDecodec 开始解码");
//    decodec_flag = true;
//    pthread_create(&posixInfo->playVideo_id, nullptr, run_video_decodec, nullptr);
//    pthread_create(&posixInfo->playAudio_id, nullptr, run_audio_decodec, nullptr);
//
//    pthread_join(posixInfo->read_id, nullptr);
//    pthread_join(posixInfo->playVideo_id, nullptr);
//    pthread_join(posixInfo->playAudio_id, nullptr);
//}


void stopDecodec() {
    decodec_flag = false;
}

//void setDecodecListener(DecodecListener *decodecListener) {
//    pDecodecListener = decodecListener;
//}
